/*
 *------------------------------------------------------------------------------
 * @File      :    imx307_mipi.c
 * @Date      :    2021-3-20
 * @Author    :    lomboswer <lomboswer@lombotech.com>
 * @Brief     :    Source file for MDP(Media Development Platform).
 *
 * Copyright (C) 2020-2021, LomboTech Co.Ltd. All rights reserved.
 *------------------------------------------------------------------------------
 */
#include "ei_comm_camera.h"

#include "camera_usr.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#define SNS_ID 307
#define SNS_NAME  "imx307_mipi"
#define DEV_TYPE MCSI

static VISS_DEV gaVissDev[ISP_MAX_DEV_NUM] = {-1};
static SNS_STATE_S g_sastSns[VISS_MAX_DEV_NUM];

#define WDR2TO1_DECREASING_EXP_RATIO_MODE 1
/*
    RHS1 limitation:
    2n + 5
    RHS1 <= FSC - BRL*2 -21
*/

#define VMAX_1080P (0x465)
#define VMAX_720P (0x2ee)

#define WDR2TO1_RHS1_720P (VMAX_720P*2 - 735*2 - 21)
#define WDR3TO1_RHS1_720P (0x55)
#define WDR3TO1_RHS2_720P (0x5F)

#define WDR2TO1_RHS1_1080P_DEFAULT (VMAX_1080P*2 - 1109*2 - 21)
#define WDR2TO1_RHS1_1080P (0x65)
#define WDR3TO1_RHS1_1080P (0x85)
#define WDR3TO1_RHS2_1080P (0x92)

#define WDR2TO1_LM_RATIO (8)
#define WDR3TO1_LM_RATIO (32)
#define WDR3TO1_MS_RATIO (16)


static const SNS_REG_S s_aRaw1080p60fps4Lane[] = {
	{0x3000, 0x01},
	{0x3002, 0x00},
	{0x3005, 0x01},
	{0x3405, 0x10},//tbl20210728
	{0x3007, 0x00},
	{0x3407, 0x03},
	{0x3009, 0x01},//tbl20210728
	{0x300A, 0xF0},
	{0x3011, 0x02},
	{0x3414, 0x0A},
	{0x3018, 0x65},
	{0x3418, 0x49},
	{0x3019, 0x04},
	{0x3419, 0x04},
	{0x301C, 0x98},//tbl20210728
	{0x301D, 0x08},//tbl20210728
	{0x3129, 0x00},
	{0x313B, 0x61},
	{0x3441, 0x0C},
	{0x3442, 0x0C},
	{0x3443, 0x03},
	{0x3444, 0x20},
	{0x3445, 0x25},
	{0x3046, 0x01},
	{0x3446, 0x57},//tbl20210728
	{0x3447, 0x00},
	{0x3448, 0x37},//tbl20210728
	{0x3449, 0x00},
	{0x344A, 0x1F},//tbl20210728
	{0x304B, 0x0A},
	{0x344B, 0x00},
	{0x344C, 0x1F},//tbl20210728
	{0x344D, 0x00},
	{0x344E, 0x1F},//tbl20210728
	{0x344F, 0x00},
	{0x3450, 0x77},//tbl20210728
	{0x3451, 0x00},
	{0x3452, 0x1F},//tbl20210728
	{0x3453, 0x00},
	{0x3454, 0x17},//tbl20210728
	{0x3455, 0x00},
	{0x305C, 0x18},
	{0x305D, 0x03},
	{0x305E, 0x20},
	{0x315E, 0x1A},
	{0x305F, 0x01},
	{0x3164, 0x1A},
	{0x3472, 0x9C},
	{0x3473, 0x07},
	{0x317C, 0x00},
	{0x3480, 0x49},
	{0x309E, 0x4A},
	{0x309F, 0x4A},
	{0x30D2, 0x19},
	{0x30D7, 0x03},
	{0x31EC, 0x0E},
	{0x3000, 0x00},
	{0x3001, 0x00},
	{0x3002, 0x00},
};

static const SNS_REG_S s_aRaw1080p30fps2Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},
    /* setting */
    {0x3005, 0x01},
    {0x3007, 0x00},
    {0x3009, 0x02},
    {0x300A, 0xF0},
    {0x300B, 0x00},
    {0x3011, 0x0A},
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x301C, 0x30},
    {0x301D, 0x11},/* H max */
    {0x3046, 0x01},
    {0x304B, 0x0A},
    {0x305C, 0x18},
    {0x305D, 0x03},
    {0x305E, 0x20},
    {0x305F, 0x01},
    {0x309E, 0x4A},
    {0x309F, 0x4A},

    {0x311C, 0x0E},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x313B, 0x41},
    {0x315E, 0x1A},
    {0x3164, 0x1A},
    {0x317C, 0x00},
    {0x31EC, 0x0E},

    /* These registers are set in CSI-2 interface only. */
    {0x3405, 0x10},
    {0x3407, 0x01},
    {0x3414, 0x0A},
    {0x3418, 0x49},
    {0x3419, 0x04},/* y-out size */
    {0x3441, 0x0C},/* 0x0A: RAW10, 0x0C: RAW12 */
    {0x3442, 0x0C},/* 0x0A: RAW10, 0x0C: RAW12 */
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3445, 0x25},
    {0x3446, 0x57},
    {0x3447, 0x00},
    {0x3448, 0x37},
    {0x3449, 0x00},
    {0x344A, 0x1F},
    {0x344B, 0x00},
    {0x344C, 0x1F},
    {0x344D, 0x00},
    {0x344E, 0x1F},
    {0x344F, 0x00},
    {0x3450, 0x77},
    {0x3451, 0x00},
    {0x3452, 0x1F},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x3472, 0x9c},
    {0x3473, 0x07},/* x-out size */
    {0x3480, 0x49},
    /* stanby cancel */
    /*
     *{0x3000, 0x00},
     *{0x3001, 0x00},
     *{0x3002, 0x00},
     */
    /* 0x308c, 0x11, */
    /* gain: 0x3014 0x3009 */
    /* shutter: 0x3020 0x3021 0x3022*/

    /* gain: 0x34a8, 0x34a9 */
    /* shutter: 0x34b1 0x34b2 0x34b3 */

};

static const SNS_REG_S s_aRaw1080p25fps2Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},
    /* setting */
    {0x3005, 0x01},
    {0x3007, 0x00},
    {0x3009, 0x02},
    {0x300A, 0xF0},
    {0x300B, 0x00},
    {0x3011, 0x0A},
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x301C, 0xa0},
    {0x301D, 0x14},/* H max */
    {0x3046, 0x01},
    {0x304B, 0x0A},
    {0x305C, 0x18},
    {0x305D, 0x03},
    {0x305E, 0x20},
    {0x305F, 0x01},
    {0x309E, 0x4A},
    {0x309F, 0x4A},

    {0x311C, 0x0E},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x313B, 0x41},
    {0x315E, 0x1A},
    {0x3164, 0x1A},
    {0x317C, 0x00},
    {0x31EC, 0x0E},

    /* These registers are set in CSI-2 interface only. */
    {0x3405, 0x10},
    {0x3407, 0x01},
    {0x3414, 0x0A},
    {0x3418, 0x49},
    {0x3419, 0x04},/* y-out size */
    {0x3441, 0x0C},/* 0x0A: RAW10, 0x0C: RAW12 */
    {0x3442, 0x0C},/* 0x0A: RAW10, 0x0C: RAW12 */
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3445, 0x25},
    {0x3446, 0x57},
    {0x3447, 0x00},
    {0x3448, 0x37},
    {0x3449, 0x00},
    {0x344A, 0x1F},
    {0x344B, 0x00},
    {0x344C, 0x1F},
    {0x344D, 0x00},
    {0x344E, 0x1F},
    {0x344F, 0x00},
    {0x3450, 0x77},
    {0x3451, 0x00},
    {0x3452, 0x1F},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x3472, 0x9c},
    {0x3473, 0x07},/* x-out size */
    {0x3480, 0x49},
    /* stanby cancel */
    /*
     *{0x3000, 0x00},
     *{0x3001, 0x00},
     *{0x3002, 0x00},
     */
    /* 0x308c, 0x11, */
    /* gain: 0x3014 0x3009 */
    /* shutter: 0x3020 0x3021 0x3022*/

    /* gain: 0x34a8, 0x34a9 */
    /* shutter: 0x34b1 0x34b2 0x34b3 */

};

static const SNS_REG_S s_aRaw720p10fps2Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},
    /* setting */
    {0x3005, 0x01},
    {0x3007, 0x10},
    {0x3009, 0x02},
    {0x300a, 0xf0},
    {0x3011, 0x0a},
    {0x3018, 0xee},
    {0x3019, 0x02},
    // for FPGA
    {0x301c, 0x20},
    {0x301d, 0x67},
    {0x3046, 0x01},
    {0x304b, 0x0a},
    {0x305c, 0x20},
    {0x305d, 0x00},
    {0x305e, 0x20},
    {0x305f, 0x01},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    /* color bar */
    //{0x308c, 0x25},
    {0x311c, 0x0e},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x313b, 0x41},
    {0x315e, 0x1a},
    {0x3164, 0x1a},
    {0x317c, 0x00},
    {0x31ec, 0x0e},
    {0x3405, 0x10},
    {0x3407, 0x01},
    {0x3414, 0x04},
    {0x3418, 0xd9},
    {0x3419, 0x02},
    /* 0A0Ah: RAW10, 0C0Ch: RAW12 */
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3445, 0x25},
    {0x3446, 0x4F},
    {0x3447, 0x00},
    {0x3448, 0x2F},
    {0x3449, 0x00},
    {0x344a, 0x17},
    {0x344b, 0x00},
    {0x344c, 0x17},
    {0x344d, 0x00},
    {0x344e, 0x17},
    {0x344f, 0x00},
    {0x3450, 0x57},
    {0x3451, 0x00},
    {0x3452, 0x17},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x3472, 0x1c},
    {0x3473, 0x05},
    {0x3480, 0x49},
    /* stanby cancel */
    {0x3000, 0x00},
    {0x3001, 0x00},
    {0x3002, 0x00},

};

/* 720P, D-PHY: 300Mhz */
static const SNS_REG_S s_aRaw720p30fps2Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},
    /* setting */
    {0x3005, 0x01},
    {0x3007, 0x10},
    {0x3009, 0x02},
    {0x300a, 0xf0},
    {0x3011, 0x0a},
    {0x3018, 0xee},
    {0x3019, 0x02},
    {0x301c, 0xc8},
    {0x301d, 0x19},
    // for FPGA
    //{0x301c, 0x20},
    //{0x301d, 0x67},
    {0x3046, 0x01},
    {0x304b, 0x0a},
    {0x305c, 0x20},
    {0x305d, 0x00},
    {0x305e, 0x20},
    {0x305f, 0x01},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    /* color bar */
    //{0x308c, 0x25},
    {0x311c, 0x0e},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x313b, 0x41},
    {0x315e, 0x1a},
    {0x3164, 0x1a},
    {0x317c, 0x00},
    {0x31ec, 0x0e},
    {0x3405, 0x10},
    {0x3407, 0x01},
    {0x3414, 0x04},
    {0x3418, 0xd9},
    {0x3419, 0x02},
    /* 0A0Ah: RAW10, 0C0Ch: RAW12 */
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3445, 0x25},
    {0x3446, 0x4F},
    {0x3447, 0x00},
    {0x3448, 0x2F},
    {0x3449, 0x00},
    {0x344a, 0x17},
    {0x344b, 0x00},
    {0x344c, 0x17},
    {0x344d, 0x00},
    {0x344e, 0x17},
    {0x344f, 0x00},
    {0x3450, 0x57},
    {0x3451, 0x00},
    {0x3452, 0x17},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x3472, 0x1c},
    {0x3473, 0x05},
    {0x3480, 0x49},
    /* stanby cancel */
    {0x3000, 0x00},
    {0x3001, 0x00},
    {0x3002, 0x00},

};

/*
 * 720p 60fps
 * Input Clock = 24Mhz bit rate 672Mbps
 */
static const SNS_REG_S s_aRaw720p30fps4Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    /* setting */
    {0x3005, 0x01},
    {0x3007, 0x10},
    {0x3009, 0x02},
    {0x300a, 0xf0},
    {0x3011, 0x0a},
    {0x3018, VMAX_720P & 0xFF}, /* V max */
    {0x3019, VMAX_720P >> 8},
    {0x301c, 0xc8},
    {0x301d, 0x19},
    {0x3046, 0x01},
    {0x304b, 0x0a},
    {0x305c, 0x20},
    {0x305d, 0x00},
    {0x305e, 0x20},
    {0x305f, 0x01},
    {0x309e, 0x4a},
    {0x309f, 0x4a},

    /* color bar */

    {0x311c, 0x0e},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x313b, 0x41},
    {0x315e, 0x1a},
    {0x3164, 0x1a},
    {0x317c, 0x00},
    {0x31ec, 0x0e},

    {0x3405, 0x20},
    {0x3407, 0x03},
    {0x3414, 0x04},
    {0x3418, 0xd9},
    {0x3419, 0x02},
    /* 0A0Ah: RAW10, 0C0Ch: RAW12 */
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x03},
    {0x3444, 0x20},
    {0x3445, 0x25},
    {0x3446, 0x47},
    {0x3447, 0x00},
    {0x3448, 0x17},
    {0x3449, 0x00},
    {0x344a, 0x0f},
    {0x344b, 0x00},
    {0x344c, 0x0f},
    {0x344d, 0x00},
    {0x344e, 0x0f},
    {0x344f, 0x00},
    {0x3450, 0x2b},
    {0x3451, 0x00},
    {0x3452, 0x0b},
    {0x3453, 0x00},
    {0x3454, 0x0f},
    {0x3455, 0x00},
    {0x3472, 0x1c},
    {0x3473, 0x05},
    {0x3480, 0x49},

    /* stanby cancel */
    /* 0x3000, 0x00, */
    /* 0x3001, 0x00, */
    /* 0x3002, 0x00, */

};


/*
 * 4lane init
 */
/* raw12 */
/* .mfreq = 1485*100*1000,  mipi-csi clock */
static const SNS_REG_S s_aRaw720p2fdol15fps4Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    /* setting */
    {0x3005, 0x01},
    {0x3405, 0x20},
    {0x3106, 0x11},
    {0x3007, 0x10},
    {0x3407, 0x03},
    {0x3009, 0x02},
    {0x300a, 0xf0},
    {0x300c, 0x11},
    {0x3011, 0x0a},
    {0x3414, 0x04},
    {0x3415, 0x00},
    {0x3018, VMAX_720P & 0xFF}, /* V max */
    {0x3019, VMAX_720P >> 8},
    {0x3418, 0xc6},
    {0x3419, 0x05},
    {0x301c, 0xc8},
    {0x311c, 0x0e},
    {0x301d, 0x19},
    {0x3020, 0x02},
    {0x3021, 0x00},
    {0x3024, 0x7B},
    {0x3025, 0x05},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x3030, WDR2TO1_RHS1_720P},
    {0x3031, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x03},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x47},
    {0x3447, 0x00},
    {0x3448, 0x17},
    {0x3449, 0x00},
    {0x344a, 0x0f},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x0f},
    {0x344d, 0x00},
    {0x344e, 0x0f},
    {0x344f, 0x00},
    {0x3450, 0x2b},
    {0x3451, 0x00},
    {0x3452, 0x0b},
    {0x3453, 0x00},
    {0x3454, 0x0f},
    {0x3455, 0x00},
    {0x305c, 0x20},
    {0x305d, 0x00},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0x20},
    {0x3473, 0x05},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},

    /* stanby cancel */
    /* 0x3000, 0x00, */
    /* 0x3001, 0x00, */
    /* 0x3002, 0x00, */
};
/*
 * 4lane init
 */
/* raw10 */
/* .mfreq = 1485*100*1000,  mipi-csi clock */
static const SNS_REG_S s_aRaw720p3fdol7p5fps4Lane[] = {
    /* sensor stanby */
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    /* setting */
    {0x3005, 0x01},
    {0x3405, 0x20},
    {0x3106, 0x33},
    {0x3007, 0x10},
    {0x3407, 0x03},
    {0x3009, 0x02},
    {0x300a, 0xf0},
    {0x300c, 0x21},
    {0x3011, 0x0a},
    {0x3414, 0x04},
    {0x3415, 0x00},
    {0x3018, VMAX_720P & 0xFF}, /* V max */
    {0x3019, VMAX_720P >> 8},
    {0x3418, 0x51},
    {0x3419, 0x09},
    {0x301c, 0xc8},
    {0x311c, 0x0e},
    {0x301d, 0x19},
    {0x3020, 0x05},
    {0x3021, 0x00},
    {0x3024, 0xAB},
    {0x3025, 0x00},
    {0x3028, 0xB7},
    {0x3029, 0x01},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x3030, 0xA6},
    {0x3031, 0x00},
    {0x3034, 0xB6},
    {0x3035, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x03},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x47},
    {0x3447, 0x00},
    {0x3448, 0x17},
    {0x3449, 0x00},
    {0x344a, 0x0f},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x0f},
    {0x344d, 0x00},
    {0x344e, 0x0f},
    {0x344f, 0x00},
    {0x3450, 0x2b},
    {0x3451, 0x00},
    {0x3452, 0x0b},
    {0x3453, 0x00},
    {0x3454, 0x0f},
    {0x3455, 0x00},
    {0x305c, 0x20},
    {0x305d, 0x00},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0x20},
    {0x3473, 0x05},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},
    /* RAW10 output */
    {0x3005, 0x00},
    {0x300a, 0x3c},
    {0x3418, 0xfa},
    {0x3419, 0x08},
    {0x3020, 0x04},
    {0x3024, 0x59},
    {0x3129, 0x1d},
    {0x3030, WDR3TO1_RHS1_720P},
    {0x3034, WDR3TO1_RHS2_720P},
    {0x3441, 0x0a},
    {0x3442, 0x0a},
    {0x3046, 0x00},
    {0x317c, 0x12},
    {0x31ec, 0x37},

    /* stanby cancel */
    /* 0x3000, 0x00, */
    /* 0x3001, 0x00, */
    /* 0x3002, 0x00, */
};

static const SNS_REG_S s_aRaw1080p2fdol25fps2Lane[] = {
    //sensor stanby
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    {0x3005, 0x01},
    {0x3405, 0x00},
    {0x3106, 0x11},
    {0x3007, 0x40},//0x00
    {0x3407, 0x01},
    {0x3009, 0x01},
    {0x300a, 0xf0},
    {0x300c, 0x11},
    {0x3011, 0x0a},
    {0x3414, 0x00},//0x0a
    {0x3415, 0x00},
#if WDR2TO1_DECREASING_EXP_RATIO_MODE
    {0x303a, 0x08},
    {0x303c, 0x04},
    {0x303d, 0x00},
    {0x303e, 0x41},
    {0x303f, 0x04},
    {0x3018, 0x486 & 0xFF}, /* V max */
    {0x3019, 0x486 >> 8},
    {0x301c, 0x03}, /* H max */
    {0x301d, 0x0a},
    {0x3418, 0xf6},
    {0x3419, 0x08},
#else
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x301c, 0x50}, /* H max */
    {0x301d, 0x0a},
    {0x3418, 0xb4},
    {0x3419, 0x08},
#endif
    {0x311c, 0x0e},
    {0x3020, 0x02},
    {0x3021, 0x00},
    {0x3024, 0xc9},
    {0x3025, 0x07},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x3030, WDR2TO1_RHS1_1080P},
    {0x3031, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x77},
    {0x3447, 0x00},
    {0x3448, 0x67},
    {0x3449, 0x00},
    {0x344a, 0x47},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x37},
    {0x344d, 0x00},
    {0x344e, 0x3f},
    {0x344f, 0x00},
    {0x3450, 0xff},
    {0x3451, 0x00},
    {0x3452, 0x3f},
    {0x3453, 0x00},
    {0x3454, 0x37},
    {0x3455, 0x00},
    {0x305c, 0x18},
    {0x305d, 0x03},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0xa0},
    {0x3473, 0x07},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},

    //stanby cancel
    //0x3000, 0x00,
    //0x3001, 0x00,
    //0x3002, 0x00,
};


static const SNS_REG_S s_aRaw1080p2fdol30fps2Lane[] = {
    //sensor stanby
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    {0x3005, 0x01},
    {0x3405, 0x00},
    {0x3106, 0x11},
    {0x3007, 0x40},//0x00
    {0x3407, 0x01},
    {0x3009, 0x01},
    {0x300a, 0xf0},
    {0x300c, 0x11},
    {0x3011, 0x0a},
    {0x3414, 0x00},//0x0a
    {0x3415, 0x00},
#if WDR2TO1_DECREASING_EXP_RATIO_MODE
    {0x303a, 0x08},
    {0x303c, 0x04},
    {0x303d, 0x00},
    {0x303e, 0x41},
    {0x303f, 0x04},
    {0x3018, 0x486 & 0xFF}, /* V max */
    {0x3019, 0x486 >> 8},
    {0x301c, 0x58}, /* H max */
    {0x301d, 0x08},
    {0x3418, 0xf6},
    {0x3419, 0x08},
#else
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x301c, 0x98},
    {0x301d, 0x08},
    {0x3418, 0xb4},
    {0x3419, 0x08},
#endif
    {0x311c, 0x0e},
    {0x3020, 0x02},
    {0x3021, 0x00},
    {0x3024, 0xc9},
    {0x3025, 0x07},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x3030, WDR2TO1_RHS1_1080P},
    {0x3031, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x01},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x77},
    {0x3447, 0x00},
    {0x3448, 0x67},
    {0x3449, 0x00},
    {0x344a, 0x47},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x37},
    {0x344d, 0x00},
    {0x344e, 0x3f},
    {0x344f, 0x00},
    {0x3450, 0xff},
    {0x3451, 0x00},
    {0x3452, 0x3f},
    {0x3453, 0x00},
    {0x3454, 0x37},
    {0x3455, 0x00},
    {0x305c, 0x18},
    {0x305d, 0x03},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0xa0},
    {0x3473, 0x07},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},

    //stanby cancel
    //0x3000, 0x00,
    //0x3001, 0x00,
    //0x3002, 0x00,
};

static const SNS_REG_S s_aRaw1080p2fdol30fps4Lane[] = {
    //sensor stanby
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},

    {0x3002, 0x00},
    {0x3005, 0x01},
    {0x3405, 0x10},
    {0x3106, 0x11},
    {0x3007, 0x00},
    {0x3407, 0x03},
    {0x3009, 0x01},
    {0x300a, 0xf0},
    {0x300c, 0x11},
    {0x3011, 0x0a},
    {0x3414, 0x0a},
    {0x3415, 0x00},
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x3418, 0xb4},
    {0x3419, 0x08},
    {0x301c, 0x98},
    {0x311c, 0x0e},
    {0x301d, 0x08},
    {0x3020, 0x02},
    {0x3021, 0x00},
    {0x3024, 0xc9},
    {0x3025, 0x07},
    {0x3128, 0x04},
    {0x3129, 0x00},
    {0x3030, WDR2TO1_RHS1_1080P_DEFAULT},
    {0x3031, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x03},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x57},
    {0x3447, 0x00},
    {0x3448, 0x37},
    {0x3449, 0x00},
    {0x344a, 0x1f},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x1f},
    {0x344d, 0x00},
    {0x344e, 0x1f},
    {0x344f, 0x00},
    {0x3450, 0x77},
    {0x3451, 0x00},
    {0x3452, 0x1f},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x305c, 0x18},
    {0x305d, 0x03},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0xa0},
    {0x3473, 0x07},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},

    //stanby cancel
    //0x3000, 0x00,
    //0x3001, 0x00,
    //0x3002, 0x00,
};

/*
 * 4lane init
 * raw10
 */
static const SNS_REG_S s_aRaw1080p3fdol15fps4Lane[] = {
    //sensor stanby	-
    {0x3000, 0x01},
    {0x3001, 0x01},
    {0x3002, 0x01},
    {0x3005, 0x01},
    {0x3405, 0x10},
    {0x3106, 0x33},
    {0x3007, 0x00},
    {0x3407, 0x03},
    {0x3009, 0x01},
    {0x300a, 0xf0},
    {0x300c, 0x21},
    {0x3011, 0x0a},
    {0x3414, 0x0a},
    {0x3415, 0x00},
    {0x3018, VMAX_1080P & 0xFF}, /* V max */
    {0x3019, VMAX_1080P >> 8},
    {0x3418, 0x8f},
    {0x3419, 0x0d},
    {0x301c, 0x98},
    {0x311c, 0x0e},
    {0x301d, 0x08},
    {0x3020, 0x04},
    {0x3021, 0x00},
    {0x3024, 0x89},
    {0x3025, 0x00},
    {0x3028, 0x93},
    {0x3128, 0x04},
    {0x3029, 0x01},
    {0x3129, 0x00},
    {0x3030, WDR3TO1_RHS1_1080P},
    {0x3031, 0x00},
    {0x3034, WDR3TO1_RHS2_1080P},
    {0x3035, 0x00},
    {0x313b, 0x41},
    {0x3441, 0x0c},
    {0x3442, 0x0c},
    {0x3443, 0x03},
    {0x3444, 0x20},
    {0x3045, 0x05},
    {0x3445, 0x25},
    {0x3046, 0x01},
    {0x3446, 0x57},
    {0x3447, 0x00},
    {0x3448, 0x37},
    {0x3449, 0x00},
    {0x344a, 0x1f},
    {0x304b, 0x0a},
    {0x344b, 0x00},
    {0x344c, 0x1f},
    {0x344d, 0x00},
    {0x344e, 0x1f},
    {0x344f, 0x00},
    {0x3450, 0x77},
    {0x3451, 0x00},
    {0x3452, 0x1f},
    {0x3453, 0x00},
    {0x3454, 0x17},
    {0x3455, 0x00},
    {0x305c, 0x18},
    {0x305d, 0x03},
    {0x305e, 0x20},
    {0x315e, 0x1a},
    {0x305f, 0x01},
    {0x3164, 0x1a},
    {0x3472, 0xa0},
    {0x3473, 0x07},
    {0x347b, 0x23},
    {0x317c, 0x00},
    {0x3480, 0x49},
    {0x309e, 0x4a},
    {0x309f, 0x4a},
    {0x31ec, 0x0e},

    //stanby cancel
    //0x3000, 0x00,
    //0x3001, 0x00,
    //0x3002, 0x00,
};

static CAMERA_POWER_ACT_S s_stPowerUpAct[] = {
    {SNS_RESET, SNS_DOWN},
    {SNS_DELAY, 1},
    {SNS_RESET, SNS_UP},
    {SNS_DELAY, 1},
};

static CAMERA_POWER_ACT_S s_sPowerDownAct[] = {
    {SNS_RESET, SNS_DOWN},
    {SNS_DELAY, 10},

};

/* vts:{0x3019,0x3018}
 * hts:{0x301d,0x301c}
 */
static SNS_TYPE_ATTR_S s_astSnsAttr[] = {
    {
        .enSnsType                  = IMX307_MIPI_1280_720_10FPS_RAW12_2LANE,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1280, 720},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32Pclk                    = 148500000,
        .u32Vts                     = VMAX_720P,
        .u32Hts                     = 26400,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 10,
        .astRegCfgs[0].pstRegs      = s_aRaw720p10fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw720p10fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 300000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1280_720_30FPS_RAW12_2LANE,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1280, 720},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32Pclk                    = 148500000,
        .u32Vts                     = VMAX_720P,
        .u32Hts                     = 6600,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw720p30fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw720p30fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 300000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1280_720_30FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1280, 720},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32Pclk                    = 148500000,
        .u32Vts                     = VMAX_720P,
        .u32Hts                     = 6600,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw720p30fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw720p30fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 123000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1280_720_2TO1_15FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1280, 720},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32Pclk                    = 74250000,
        .u32Vts                     = VMAX_720P,
        .u32Hts                     = 6600,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate                = 15,
        .astRegCfgs[0].pstRegs      = s_aRaw720p2fdol15fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw720p2fdol15fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 53913600,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1280_720_3TO1_7P5FPS_RAW10,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_10BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1280, 720},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_3Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32Pclk                    = 37125000,
        .u32Vts                     = VMAX_720P,
        .u32Hts                     = 6600,
        .enIspWdrMode               = WDR_MODE_3TO1_FRAME,

        .u32FrameRate                = 7,
        .astRegCfgs[0].pstRegs      = s_aRaw720p3fdol7p5fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw720p3fdol7p5fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 89856000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_25FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 149000000,
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 5280,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate                = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p25fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p25fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 445000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_30FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 149000000,
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 4400,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate                = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p30fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p30fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 445000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_2TO1_25FPS_RAW12_2LANE,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 149000000,
#if WDR2TO1_DECREASING_EXP_RATIO_MODE
        .u32Vts                     = 0x486,
        .u32Hts                     = 0xa03,
#else
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 2640,
#endif
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 25,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p2fdol25fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p2fdol25fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 891000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_2TO1_30FPS_RAW12_2LANE,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 149000000,
#if WDR2TO1_DECREASING_EXP_RATIO_MODE
        .u32Vts                     = 0x486,
        .u32Hts                     = 0x858,
#else
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 2200,
#endif
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate               = 30,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p2fdol30fps2Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p2fdol30fps2Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 891000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_2Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_2TO1_30FPS_RAW12_4LANE,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_2Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 149000000,
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 2200,
        .enIspWdrMode               = WDR_MODE_2TO1_FRAME,

        .u32FrameRate                = 30,

        .astRegCfgs[0].pstRegs      = s_aRaw1080p2fdol30fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p2fdol30fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 445500000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },
    {
        .enSnsType                  = IMX307_MIPI_1920_1080_3TO1_15FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_3Chn,
        .enWdrMode                  = VISS_WDR_MODE_DOL,

        .u32IspClk                  = 99000000,
        .u32IppuClk                 = 198000000,
        .u32Pclk                    = 74250000,
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 4400,
        .enIspWdrMode               = WDR_MODE_3TO1_FRAME,

        .u32FrameRate                = 15,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p3fdol15fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p3fdol15fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 445500000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },

    {
        .enSnsType                  = IMX307_MIPI_1920_1080_60FPS_RAW12,
        .enPixelFormat              = PIX_FMT_RGB_BAYER_12BITS,
        .enRgbSeq                   = VISS_RGB_SEQ_RGGB,
        .stSize                     = {1920, 1080},
        .u32ModuleClk               = 198000000,
        .u32Mclock                  = 37125000,
        .enWorkMode                 = VISS_WORK_MODE_1Chn,

        .u32IspClk                  = 148500000,
        .u32IppuClk                 = 297000000,
        .u32Pclk                    = 148500000,
        .u32Vts                     = VMAX_1080P,
        .u32Hts                     = 2200,
        .enIspWdrMode               = WDR_MODE_NONE,

        .u32FrameRate               = 60,
        .astRegCfgs[0].pstRegs      = s_aRaw1080p60fps4Lane,
        .astRegCfgs[0].u32RegsCnt   = ARRAY_SIZE(s_aRaw1080p60fps4Lane),

        .stDevCfg.stMcsiCfg.u32PhyFreq  = 445000000,
        .stDevCfg.stMcsiCfg.enDlanes    = VISS_LANE_NUM_4Lane,
    },
};

static int CAMERA_SetI2cInfo(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    if (pstSnsState->stI2cInfo.fd > 0) {
        return EI_SUCCESS;
    }

    pstSnsState->stI2cInfo.u8RegBits = 16;
    pstSnsState->stI2cInfo.u8ValBits = 8;
#if defined(CONFIG_ARCH_LOMBO_N7V7)
    pstSnsState->stI2cInfo.u16I2cBusNum = 3;
#else
    pstSnsState->stI2cInfo.u16I2cBusNum = 4;
#endif
    pstSnsState->stI2cInfo.u16I2cDevAddr = 0x1a;
    pstSnsState->pcName = SNS_NAME;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Detect(VISS_DEV VissDev)
{
    EI_U8 u8Tmp;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U16 u16Id;
    SNS_STATE_S *pstSnsState = EI_NULL;
    I2C_INFO_S *pstI2cInfo = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;

    CAMERA_CHECK_POINTER(pstI2cInfo->pfnReadReg);
    s32Ret = pstI2cInfo->pfnReadReg(pstSnsState, 0x31DC, &u8Tmp);
    if (s32Ret != 0) {
        PRT_VISS_ERR("tmp[0]=%x\n", u8Tmp);
        return EI_FAILURE;
    }

    u16Id = u8Tmp & 0x06;
    if (u16Id == 0x4) {
        PRT_VISS_INFO("%s ID = 0x%04x, real sensor is imx307!\n", SNS_NAME, u16Id);
    } else if (u16Id == 0x6) {
        PRT_VISS_INFO("%s ID = 0x%04x, real sensor is imx327!\n", SNS_NAME, u16Id);
    } else {
        PRT_VISS_ERR("%s ID wrong! (0x%04x != 0x4/0x6)\n", SNS_NAME, u16Id);
        return EI_FAILURE;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_Stream(VISS_DEV dev, EI_BOOL bOn)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    PRT_VISS_ERR("%s CAMERA_Stream******%d\n", SNS_NAME, bOn);

    if (bOn) {
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3000, 0x00);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3001, 0x00);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3002, 0x00);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
    } else {
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3000, 0x01);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3001, 0x01);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3002, 0x01);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("CAMERA_Stream*******%d\n", bOn);
        }
    }
    return s32Ret;

}

/* The following functions can be modified as needed */

static int CAMERA_I2cInit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    int ret = EI_SUCCESS;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    ret = CAMERA_SetI2cInfo(dev);
    CAMERA_CHECK_SUCCESS(ret);

    ret = CAMERA_I2C_Reg_Ops(&pstSnsState->stI2cInfo);
    CAMERA_CHECK_SUCCESS(ret);

    return EI_SUCCESS;
}

static int CAMERA_I2cExit(VISS_DEV dev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_PowerUp(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    MI_VISS_SnsPower(VissDev, 0xa0000000);
    CAMERA_SensorPowerUp(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_PowerDown(VISS_DEV VissDev)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(VissDev, pstSnsState);

    MI_VISS_SnsPower(VissDev, 0x00000000);

    CAMERA_SensorPowerDown(VissDev, pstSnsState);

    return 0;
}

static EI_S32 CAMERA_SetGain(ISP_DEV dev, EI_FLOAT fGain);
static EI_S32 CAMERA_SetExpTime(ISP_DEV dev, EI_FLOAT *afIntTime);

static EI_S32 CAMERA_Init(VISS_DEV dev)
{
    EI_U32 j;
    const SNS_TYPE_ATTR_S *pstSnsType;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstSnsType = pstSnsState->pstSnsAttr;
    for (j = 0; j < MAX_COF; j++) {
        s32Ret = pstSnsState->stI2cInfo.pfnwriteRegList(pstSnsState,
                pstSnsType->astRegCfgs[j].pstRegs, pstSnsType->astRegCfgs[j].u32RegsCnt);
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("%s writeRegList err\n", SNS_NAME);
            return s32Ret;
        }
    }

    /* Keep fps when reset */
    pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3018, pstSnsType->u32Vts);
    pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3019, pstSnsType->u32Vts >> 8);

    pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x301c, pstSnsType->u32Hts);
    pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x301d, pstSnsType->u32Hts >> 8);

    if ((pstSnsState->afIntTime[0] > 0.000001) && (pstSnsState->fGain >= 1.0)) {
        CAMERA_SetExpTime(pstSnsState->IspDev, pstSnsState->afIntTime);
        CAMERA_SetGain(pstSnsState->IspDev, pstSnsState->fGain);
    }

    PRT_VISS_INFO("%s writeRegList success\n", SNS_NAME);

    return s32Ret;
}

static void CAMERA_Exit(VISS_DEV dev)
{
    CAMERA_I2cExit(dev);

    return;
}

static EI_S32 CAMERA_SetImageMode(VISS_DEV dev, SNS_TYPE_E enSnsType)
{
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstSnsState->enSnsType = enSnsType;
    pstSnsState->bSyncInit = EI_FALSE;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_EnumSnstype(VISS_DEV VissDev, EI_U32 u32Index, SNS_TYPE_E *peSnstype)
{
    const SNS_TYPE_ATTR_S *pstSnsType;

    if (u32Index >= ARRAY_SIZE(s_astSnsAttr))
        return EN_ERR_NO_FOUND;

    pstSnsType = &s_astSnsAttr[u32Index];

    *peSnstype = pstSnsType->enSnsType;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFrameRate(VISS_DEV VissDev, EI_FLOAT f32Fps)
{
    I2C_INFO_S *pstI2cInfo = EI_NULL;
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts;

    SNS_GET_CTX(VissDev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);

    pstI2cInfo = &pstSnsState->stI2cInfo;
    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Vts = pstSnsState->pstSnsAttr->u32Vts;

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Hts = u32Pclk / u32Vts / f32Fps;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x301c, u32Hts);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x301d, u32Hts >> 8);
        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {
        if (pstSnsState->pstSnsAttr->u32FrameRate < f32Fps || 1 > f32Fps) {
            cprintf("1 <= set fps <= %d, set fps: %f\n", pstSnsState->pstSnsAttr->u32FrameRate, f32Fps);
            f32Fps = pstSnsState->pstSnsAttr->u32FrameRate;
        }

        u32Hts = u32Pclk / u32Vts / f32Fps / 2;

        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x301c, u32Hts);
        s32Ret += pstI2cInfo->pfnWriteReg(pstSnsState, 0x301d, u32Hts >> 8);
        if (s32Ret != 0) {
            cprintf("CAMERA_Init error\n");
            return s32Ret;
        }
    } else {
        return EN_ERR_NOT_SUPPORT;
    }

    pstSnsState->pstSnsAttr->u32Hts = u32Hts;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_InitSensorExpFunction(SENSOR_EXP_FUNC_S *pstSensorExpFunc)
{
    CAMERA_CHECK_POINTER(pstSensorExpFunc);

    memset(pstSensorExpFunc, 0, sizeof(SENSOR_EXP_FUNC_S));

    pstSensorExpFunc->pfnSensorPowerUp  = CAMERA_PowerUp;
    pstSensorExpFunc->pfnSensorPowerDown = CAMERA_PowerDown;
    pstSensorExpFunc->pfnSensorDetect   = CAMERA_Detect;
    pstSensorExpFunc->pfnSensorInit     = CAMERA_Init;
    pstSensorExpFunc->pfnSensorStream   = CAMERA_Stream;
    pstSensorExpFunc->pfnSensorExit     = CAMERA_Exit;
    pstSensorExpFunc->pfnSensorSetImageMode   = CAMERA_SetImageMode;
    pstSensorExpFunc->pfnSensorEnumSnstype   = CAMERA_EnumSnstype;
    pstSensorExpFunc->pfnSensorSetFrameRate   = CAMERA_SetFrameRate;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAeDefault(ISP_DEV dev, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{
    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_SetFps(ISP_DEV dev, EI_FLOAT f32Fps, AE_SENSOR_DEFAULT_S *pstAeSnsDft)
{
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    CAMERA_CHECK_POINTER(pstAeSnsDft);

    return CAMERA_SetFrameRate(Dev, f32Fps);
}

static EI_S32 CAMERA_SetExpTime(ISP_DEV dev, EI_FLOAT *afIntTime)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Pclk, u32Hts, u32Vts;
    EI_U32 vmax, shutter_time;
    EI_U32 lexp, mexp, sexp;
    EI_U8 rhs1, rhs2;
    EI_S32 shs1, shs2, shs3;
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    CAMERA_CHECK_POINTER(afIntTime);
    pstSnsState->afIntTime[0] = afIntTime[0];
    pstSnsState->afIntTime[1] = afIntTime[1];
    pstSnsState->afIntTime[2] = afIntTime[2];
    pstSnsState->afIntTime[3] = afIntTime[3];
    pstSnsState->IspDev = dev;
    CAMERA_CHECK_POWERON(pstSnsState);

    u32Pclk = pstSnsState->pstSnsAttr->u32Pclk;
    u32Hts = pstSnsState->pstSnsAttr->u32Hts;
    u32Vts = pstSnsState->pstSnsAttr->u32Vts;

    if ((u32Pclk == 0) || (u32Hts == 0) || (u32Vts == 0)) {
        PRT_VISS_ERR("error! u32Pclk %d, u32Hts %d, u32Vts %d\n", u32Pclk, u32Hts, u32Vts);
        return EI_FAILURE;
    }

    /* afIntTime[0] long/medium/short/vshort exptime (s) */
    shutter_time = afIntTime[0] * u32Pclk / u32Hts;
    if (shutter_time < 2)
        shutter_time = 2;

    //printf("exp_time: %d, %f(s)!\n", shutter_time, afIntTime[0]);

    if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_NONE) {
        if (shutter_time > u32Vts - 2)
            vmax = shutter_time + 2;
        else
            vmax = u32Vts;
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3018, ((vmax >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3019, ((vmax >> 8) & 0xff));

        shs1 = vmax - (shutter_time + 1);

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3020, ((shs1 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3021, ((shs1 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3022, ((shs1 >> 16) & 0x3));
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }
    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_2TO1_FRAME) {
        s32Ret = pstSnsState->stI2cInfo.pfnReadReg(pstSnsState, 0x3030, &rhs1);
        CAMERA_CHECK_SUCCESS(s32Ret);

        if (afIntTime[1] < 1)
            afIntTime[1] = WDR2TO1_LM_RATIO;

        if (shutter_time > 2 * u32Vts - 2)
            lexp = 2 * u32Vts - 2;
        else
            lexp = shutter_time;
        mexp = shutter_time / afIntTime[1];

        if (mexp < 2)
            mexp = 2;

        lexp = mexp * afIntTime[1];

        shs2 = 2 * u32Vts - lexp - 1;
        shs1 = rhs1 - mexp - 1;
        if (shs1 < 2) {
            shs1 = 2;
            mexp = rhs1 - shs1 - 1;
            lexp = mexp * afIntTime[1];
            shs2 = 2 * u32Vts - lexp - 1;
        }
        if (shs2 < shs1 + 2)
            shs2 = shs1 + 2;

        //printf("2in1 exp: %d %d, rhs: %d, shs: %d %d\n", lexp, mexp, rhs1, shs1, shs2);

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3020, ((shs1 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3021, ((shs1 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3022, ((shs1 >> 16) & 0x3));

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3024, ((shs2 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3025, ((shs2 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3026, ((shs2 >> 16) & 0x3));
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }

        shutter_time = lexp;
    } else if (pstSnsState->pstSnsAttr->enIspWdrMode == WDR_MODE_3TO1_FRAME) {
        s32Ret = pstSnsState->stI2cInfo.pfnReadReg(pstSnsState, 0x3030, &rhs1);
        CAMERA_CHECK_SUCCESS(s32Ret);

        s32Ret = pstSnsState->stI2cInfo.pfnReadReg(pstSnsState, 0x3034, &rhs2);
        CAMERA_CHECK_SUCCESS(s32Ret);

        if (afIntTime[1] < 1)
            afIntTime[1] = WDR3TO1_LM_RATIO;
        if (afIntTime[2] < 1)
            afIntTime[2] = WDR3TO1_MS_RATIO;

        if (shutter_time > 4 * u32Vts - 2)
            lexp = 4 * u32Vts - 2;
        else
            lexp = shutter_time;
        mexp = shutter_time / afIntTime[1];
        sexp = mexp / afIntTime[2];

        if (sexp < 2)
            sexp = 2;

        mexp = sexp * afIntTime[2];
        lexp = mexp * afIntTime[1];

        shs3 = 4 * u32Vts - lexp - 1;
        shs1 = rhs1 - mexp - 1;
        shs2 = rhs2 - sexp - 1;

        if (shs1 < 3) {
            shs1 = 3;
            mexp = rhs1 - shs1 - 1;
            lexp = mexp * afIntTime[1];
            sexp = mexp / afIntTime[2];
            shs3 = 4 * u32Vts - lexp - 1;
            shs2 = rhs2 - sexp - 1;
        }
        if (shs2 < shs1 + 3)
            shs2 = shs1 + 3;
        if (shs3 < shs2 + 3)
            shs3 = shs2 + 3;

        //printf("3in1 exp: %d %d %d, rhs: %d %d, shs: %d %d %d\n", lexp, mexp, sexp, rhs1, rhs2, shs1, shs2, shs3);

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3020, ((shs1 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3021, ((shs1 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3022, ((shs1 >> 16) & 0x3));

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3024, ((shs2 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3025, ((shs2 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3026, ((shs2 >> 16) & 0x3));

        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3028, ((shs3 >> 0) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3029, ((shs3 >> 8) & 0xff));
        s32Ret += pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x302a, ((shs3 >> 16) & 0x3));
        if (s32Ret != EI_SUCCESS) {
            PRT_VISS_ERR("\n");
        }

        shutter_time = lexp;
    }

    afIntTime[0] = (EI_FLOAT)shutter_time * u32Hts / u32Pclk;
    if (afIntTime[0] < 0.00001) {
        afIntTime[0] = 0.00001;
    }

    return s32Ret;
}

static EI_U32 GainTable[231] = {
       256,    264,    274,    283,    293,    304,    314,    326,
       337,    349,    361,    374,    387,    401,    415,    429,
       444,    460,    476,    493,    510,    528,    547,    566,
       586,    607,    628,    650,    673,    697,    721,    746,
       773,    800,    828,    857,    887,    918,    951,    984,
      1019,   1054,   1092,   1130,   1170,   1211,   1253,   1297,
      1343,   1390,   1439,   1490,   1542,   1596,   1652,   1710,
      1771,   1833,   1897,   1964,   2033,   2104,   2178,   2255,
      2334,   2416,   2501,   2589,   2680,   2774,   2872,   2973,
      3077,   3185,   3297,   3413,   3533,   3657,   3786,   3919,
      4057,   4199,   4347,   4500,   4658,   4822,   4991,   5167,
      5348,   5536,   5731,   5932,   6141,   6356,   6580,   6811,
      7050,   7298,   7555,   7820,   8095,   8379,   8674,   8979,
      9294,   9621,   9959,  10309,  10671,  11046,  11435,  11836,
     12252,  12683,  13129,  13590,  14068,  14562,  15074,  15604,
     16152,  16720,  17307,  17915,  18545,  19197,  19871,  20570,
     21293,  22041,  22816,  23617,  24447,  25306,  26196,  27116,
     28069,  29056,  30077,  31134,  32228,  33361,  34533,  35747,
     37003,  38303,  39649,  41043,  42485,  43978,  45523,  47123,
     48779,  50494,  52268,  54105,  56006,  57974,  60012,  62121,
     64304,  66564,  68903,  71324,  73831,  76425,  79111,  81891,
     84769,  87748,  90832,  94024,  97328, 100748, 104289, 107954,
    111748, 115675, 119740, 123948, 128303, 132812, 137480, 142311,
    147312, 152489, 157848, 163395, 169137, 175081, 181234, 187603,
    194195, 201020, 208084, 215397, 222966, 230802, 238913, 247309,
    256000, 264996, 274308, 283948, 293927, 304256, 314948, 326016,
    337473, 349333, 361609, 374317, 387471, 401088, 415183, 429773,
    444877, 460510, 476694, 493446, 510787, 528737, 547318, 566552,
    586462, 607071, 628405, 650489, 673348, 697011, 721506
};
EI_U8 hcg;

static EI_S32 CAMERA_SetGain(ISP_DEV dev, EI_FLOAT fGain)
{
    SNS_STATE_S *pstSnsState = EI_NULL;
    EI_S32 s32Ret = EI_SUCCESS;
    EI_U32 u32Gain, db_idx;
    VISS_DEV Dev;

    SNS_GET_ISP_TO_VISS(dev, Dev);

    SNS_GET_CTX(Dev, pstSnsState);
    CAMERA_CHECK_POINTER(pstSnsState);
    pstSnsState->fGain = fGain;
    CAMERA_CHECK_POWERON(pstSnsState);

    if (fGain < 1)
        fGain = 1;

    //printf("gain: %f!\n", fGain);

    u32Gain = fGain * 256;

    for (db_idx = 0; db_idx < 231; db_idx++) {
        if (u32Gain <= GainTable[db_idx])
            break;
    }

    s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3014, db_idx);
    if (s32Ret != EI_SUCCESS) {
        PRT_VISS_ERR("\n");
    }
#if 0
    if ((hcg & 0x10) == 0) {
        s32Ret = pstSnsState->stI2cInfo.pfnReadReg(pstSnsState, 0x3009, &hcg);
        hcg = hcg | 0x10;
        s32Ret = pstSnsState->stI2cInfo.pfnWriteReg(pstSnsState, 0x3009, hcg);
    }
#endif
    return s32Ret;
}

static EI_S32 CAMERA_InitAeExpFunction(AE_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S));

    pstExpFuncs->pfnGetAeDefault    = CAMERA_GetAeDefault;
    pstExpFuncs->pfnSetFps          = CAMERA_SetFps;
    pstExpFuncs->pfnSetExpTime      = CAMERA_SetExpTime;
    pstExpFuncs->pfnSetGain         = CAMERA_SetGain;

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetAwbDefault(ISP_DEV dev, AWB_SENSOR_DEFAULT_S *pstAwbSnsDft)
{
    CAMERA_CHECK_POINTER(pstAwbSnsDft);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_InitAwbExpFunction(AWB_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
    CAMERA_CHECK_POINTER(pstExpFuncs);

    memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S));
    pstExpFuncs->pfnGetAwbDefault = CAMERA_GetAwbDefault;

    return EI_SUCCESS;
}

/****************************************************************************
 * callback structure                                                       *
 ****************************************************************************/

static EI_S32 CAMERA_CtxInit(VISS_DEV dev)
{
    SNS_STATE_S *pastSnsStateCtx = EI_NULL;

    SNS_GET_CTX(dev, pastSnsStateCtx);

    CAMERA_CHECK_POINTER(pastSnsStateCtx);

    memset(pastSnsStateCtx, 0, sizeof(SNS_STATE_S));

    pastSnsStateCtx->pstPowerUpAct      = s_stPowerUpAct;
    pastSnsStateCtx->pstPowerDownAct    = s_sPowerDownAct;
    pastSnsStateCtx->u8PwrUpActs        = ARRAY_SIZE(s_stPowerUpAct);
    pastSnsStateCtx->u8PwrDnActs        = ARRAY_SIZE(s_sPowerDownAct);

    return EI_SUCCESS;
}

static EI_VOID CAMERA_CtxExit(VISS_DEV dev)
{
    return ;
}

static EI_S32 CAMERA_RegisterVissCallback(VISS_DEV dev, SNS_TYPE_E enType)
{
    EI_S32 s32Ret;
    SENSOR_S stSns = {0};
    EI_U32 i;
    SNS_STATE_S *pstSnsState = EI_NULL;

    s32Ret = CAMERA_CtxInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    SNS_GET_CTX(dev, pstSnsState);

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsState->pstSnsAttr = &s_astSnsAttr[i];
            break;
        }
    }

    pstSnsState->enSnsType = enType;
    pstSnsState->Dev = dev;

    if (i >= ARRAY_SIZE(s_astSnsAttr)) {
        PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);
        return EI_FAILURE;
    }

    s32Ret = CAMERA_I2cInit(dev);
    if (EI_SUCCESS != s32Ret) {
        return EI_FAILURE;
    }

    stSns.stSnsAttrInfo.eSensorId = SNS_ID;
    stSns.stSnsAttrInfo.enDevType = DEV_TYPE;
    stSns.stSnsAttrInfo.pstSns = pstSnsState;

    s32Ret  = CAMERA_InitSensorExpFunction(&stSns.stSnsAttrInfo.stSnsExp);
    s32Ret |= VISS_SensorRegCallBack(dev, &stSns);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor register callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = CAMERA_OpenI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterVissCallback(VISS_DEV dev)
{
    EI_S32 s32Ret;
    SNS_STATE_S *pstSnsState = EI_NULL;

    SNS_GET_CTX(dev, pstSnsState);

    s32Ret = CAMERA_ExitI2c(pstSnsState);
    CAMERA_CHECK_SUCCESS(s32Ret);

    s32Ret = VISS_SensorUnRegCallBack(dev, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        PRT_VISS_ERR("%s sensor unregister callback function failed!\n", SNS_NAME);
        return s32Ret;
    }

    CAMERA_CtxExit(dev);

    return EI_SUCCESS;
}

static EI_S32 CAMERA_RegisterIspCallback(VISS_DEV Dev, ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;
    AE_SENSOR_REGISTER_S  stAeRegister;
    AWB_SENSOR_REGISTER_S stAwbRegister;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    SNS_SET_ISP_TO_VISS(dev, Dev);

    stAeRegister.SnsId = SNS_ID;
    stAwbRegister.SnsId = SNS_ID;

    s32Ret  = CAMERA_InitAeExpFunction(&stAeRegister.stSnsExp);
    s32Ret |= EI_MI_AE_SensorRegCallBack(dev, pstAeLib, &stAeRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret  = CAMERA_InitAwbExpFunction(&stAwbRegister.stSnsExp);
    s32Ret |= EI_MI_AWB_SensorRegCallBack(dev, pstAwbLib, &stAwbRegister);

    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s register callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_UnregisterIspCallback(ISP_DEV dev, ISP_3ALIB_S *pstAeLib, ISP_3ALIB_S *pstAwbLib)
{
    EI_S32 s32Ret;

    CAMERA_CHECK_POINTER(pstAeLib);
    CAMERA_CHECK_POINTER(pstAwbLib);

    s32Ret = EI_MI_AE_SensorUnRegCallBack(dev, pstAeLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to ae lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    s32Ret = EI_MI_AWB_SensorUnRegCallBack(dev, pstAwbLib, SNS_ID);
    if (EI_SUCCESS != s32Ret) {
        EI_TRACE_ISP(EI_DBG_ERR, "%s unregister callback function to awb lib failed!\n", SNS_NAME);
        return s32Ret;
    }

    return EI_SUCCESS;
}

static EI_S32 CAMERA_GetVissDevAttrBySns(SNS_TYPE_E enType,
    VISS_DEV_ATTR_S *pstVissDevAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissDevAttr->stSize          = pstSnsType->stSize;
            pstVissDevAttr->enWorkMode      = pstSnsType->enWorkMode;
            pstVissDevAttr->mClock          = pstSnsType->u32Mclock;
            pstVissDevAttr->enPixelFormat   = pstSnsType->enPixelFormat;
            pstVissDevAttr->enWdrMode       = pstSnsType->enWdrMode;
            pstVissDevAttr->enIspWdrMode    = pstSnsType->enIspWdrMode;
            pstVissDevAttr->enRgbSeq        = pstSnsType->enRgbSeq;
            pstVissDevAttr->u32ModuleClk    = pstSnsType->u32ModuleClk;
            pstVissDevAttr->u32Fps          = pstSnsType->u32FrameRate;
            pstVissDevAttr->u32IspClk       = pstSnsType->u32IspClk;
            pstVissDevAttr->u32IppuClk      = pstSnsType->u32IppuClk;
            pstVissDevAttr->pcSnsName       = SNS_NAME;
            pstVissDevAttr->stDevCfg        = pstSnsType->stDevCfg;

            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this dev configuration", SNS_NAME);

    return EI_FAILURE;
}

static EI_S32 CAMERA_GetVissChnAttrBySns(SNS_TYPE_E enType,
    VISS_CHN_ATTR_S *pstVissChnAttr)
{
    EI_U32 i;
    const SNS_TYPE_ATTR_S *pstSnsType;

    for (i = 0; i < ARRAY_SIZE(s_astSnsAttr); i++) {
        if (enType == s_astSnsAttr[i].enSnsType) {
            pstSnsType = &s_astSnsAttr[i];
            pstVissChnAttr->stSize          = pstSnsType->stSize;
            pstVissChnAttr->enPixelFormat   = pstSnsType->enPixelFormat;
            pstVissChnAttr->stFrameRate.s32SrcFrameRate     = pstSnsType->u32FrameRate;
            return EI_SUCCESS;
        }
    }

    PRT_VISS_ERR("%s does not support this chn configuration", SNS_NAME);

    return EI_FAILURE;

}

CAMERA_OBJ_S stCameraImx307mipiObj = {
    .pfnRegisterVissCallback    = CAMERA_RegisterVissCallback,
    .pfnUnRegisterVissCallback  = CAMERA_UnregisterVissCallback,
    .pfnRegisterIspCallback     = CAMERA_RegisterIspCallback,
    .pfnUnRegisterIspCallback   = CAMERA_UnregisterIspCallback,
    .pfnGetVissDevAttrBySns     = CAMERA_GetVissDevAttrBySns,
    .pfnGetVissChnAttrBySns     = CAMERA_GetVissChnAttrBySns,
};


#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

